{
  //  后置通知，，在某个方法执行完毕之后调用后置通知

  let readonly=function(target,name,descriptor){
    console.log('descriptor',descriptor)
    // descriptor {value: ƒ, writable: true, enumerable: false, configurable: true}
    console.log('target',target)
    // target {constructor: ƒ, time: ƒ}
    console.log('name',name)
    //  name time
    descriptor.writable=false;
    return descriptor
  };
    let readonly2=function(){
        console.log('readonly2')
    //    readonly2
    }
  //  设置只读
  class Test{
    @readonly
    time(){
      return '2017-03-11'
    }
    // 这个注解只要是个方法就行，代表在time2执行之前调用readonly2
    @readonly2
    time2(){
          return '201s7-03-11'
      }
  }

  let test=new Test();
    test.time2();
  // test.time=function(){
  //   console.log('reset time');
  // };

  console.log(test.time());
}


{
  // 添加静态属性
  let typename=function(target,name,descriptor){
    target.myname='hello';
  }

  @typename
  class Test{

  }

  console.log('类修饰符',Test.myname);
  // 第三方库修饰器的js库：core-decorators; npm install core-decorators
}

{
  //  这里使用了尾递归，也可以说是闭包
  //  这是一个简单的日志记录器。。还不如直接记录  name...
  //  这样写应该是有特殊用途吧
  let log=(type)=>{
    return function(target,name,descriptor){
      let src_method=descriptor.value;
      descriptor.value=(...arg)=>{
        src_method.apply(target,arg);
        console.info(`log ${type}`);
      }
    }
  }
  // @log('show')因为他的返回值是一个方法。。
  class AD{
    @log('show')
    show(){
      console.info('ad is show')
    }
    @log('click')
    click(){
      console.info('ad is click');
    }
    //  注意这里只能用箭头函数写
    @((type='clicktest')=>{
        return function(target,name,descriptor){
            let src_method=descriptor.value;
            descriptor.value=(...arg)=>{
                src_method.apply(target,arg);
                console.info(`log ${type}`);
            }
        }
    })('xxxx')
    clicktest(){
          console.info('ad is clicktest');
      }
      @(function(type){
          return function(target,name,descriptor){
              let src_method=descriptor.value;
              descriptor.value=(...arg)=>{
                  src_method.apply(target,arg);
                  console.info(`log ${type}`);
              }
          }
      })('clicktest2')
      clicktest2(){
          console.info('ad is clicktest2');
      }
      @function(target,name,descriptor){
              let src_method=descriptor.value;
              descriptor.value=(...arg)=>{
                  src_method.apply(target,arg);
                  console.info(`log ${name}`);
              }}
      clicktest3(){
          console.info('ad is clicktest3');
      }
      @(function(target,name,descriptor){
          let src_method=descriptor.value;
          descriptor.value=(...arg)=>{
              src_method.apply(target,arg);
              console.info(`log ${name}`);
          }})
      clicktest4(){
          console.info('ad is clicktest4');
      }
  }

  let ad=new AD();
  ad.show();
  ad.click();
  ad.clicktest();
  ad.clicktest2();
  ad.clicktest3();
  ad.clicktest4();
}
